package org.jeecg.modules.flowable.service.impl;

import com.alibaba.fastjson.JSONObject;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import org.apache.commons.collections.CollectionUtils;
import org.flowable.engine.HistoryService;
import org.flowable.engine.RuntimeService;
import org.flowable.engine.TaskService;
import org.flowable.engine.history.HistoricProcessInstance;
import org.flowable.engine.runtime.ProcessInstance;
import org.flowable.task.api.Task;
import org.flowable.task.api.history.HistoricTaskInstance;
import org.jeecg.modules.flowable.common.util.IdUtil;
import org.jeecg.modules.flowable.common.util.json.ObjectConvert;
import org.jeecg.modules.flowable.common.util.validation.AssertValid;
import org.jeecg.modules.flowable.common.util.validation.MustParamValidation;
import org.jeecg.modules.flowable.entity.*;
import org.jeecg.modules.flowable.exception.ModuleFlowableException;
import org.jeecg.modules.flowable.mapper.*;
import org.jeecg.modules.flowable.service.*;
import org.jeecg.modules.flowable.service.bo.Attr;
import org.jeecg.modules.flowable.service.bo.FengForm;
import org.jeecg.modules.flowable.service.bo.TaskConfList;
import org.jeecg.modules.flowable.service.bo.taskconf.TaskConfResult;
import org.jeecg.modules.flowable.service.bo.taskdetail.*;
import org.jeecg.modules.flowable.system.core.SystemUser;
import org.jeecg.modules.flowable.system.etc.SystemUserUtil;
import org.jeecg.modules.flowable.system.service.fs.FsManagerService;
import org.jeecg.modules.flowable.system.service.uplode.bo.WebFsDataResult;
import org.jeecg.modules.flowable.util.ObjectUtil;
import org.joda.time.DateTime;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.jdbc.core.JdbcTemplate;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.math.BigDecimal;
import java.time.LocalDateTime;
import java.time.ZoneId;
import java.util.*;
import java.util.stream.Collectors;

/**
 * Title:  <br>
 * Desc:  <br>
 * Date: 6/17/22 5:49 PM <br>
 * Company: 联通（辽宁）产业互联网有限公司 <br>
 *
 * @author zxd
 * @version 1.0.0
 */
@Service
public class FlowProcServiceImpl implements FlowProcService {

    @Autowired
    private ExtFlowableMapper extFlowableMapper;

    @Autowired
    private TActMatterInstMapper tActMatterInstMapper;

    @Autowired
    private FormService formService;

    @Autowired
    private TActMatterInstFormdataMapper tActMatterInstFormdataMapper;

    @Autowired
    private FlowableService flowableService;

    @Autowired
    private RuntimeService runtimeService;

    @Autowired
    private TActRuActinstMapper tActRuActinstMapper;

    @Autowired
    private TActFengFormDataMapper tActFengFormDataMapper;

    @Autowired
    private TActRuActinstAttrMapper tActRuActinstAttrMapper;

    @Autowired
    private TActTaskConfMapper tActTaskConfMapper;

    @Autowired
    private FsManagerService fsManagerInf;

    @Autowired
    private JdbcTemplate jdbcTemplate;

    @Autowired
    private TaskService taskService;

    @Autowired
    private HistoryService historyService;

    @Autowired
    private ITActFengFormDataService iTActFengFormDataService;

    @Autowired
    private ITActRuActinstAttrService iTActRuActinstAttrService;

    @Autowired
    private TActTheendMapper tActTheendMapper;

    @Override
    public List<Map<String, Object>> queryMyTodo(String argUserId) {
        List<Map<String, Object>> maps = extFlowableMapper.queryMyTodo(argUserId);
        return maps;
    }

    @Override
    public Page<Map<String, Object>> queryMyTodoByPage(String argUserId, Integer argCurrPage, Integer argPageSize) {
        Page<Map<String, Object>> page = extFlowableMapper.queryMyTodo(new Page<Map>(argCurrPage, argPageSize), argUserId);
        return page;
    }

    @Override
    public Page<Map<String, Object>> queryMyFlow(String argUserId, Integer argCurrPage, Integer argPageSize) {
        Page<Map<String, Object>> page = extFlowableMapper.queryMyFlow(new Page<Map>(argCurrPage, argPageSize), argUserId);
        return page;
    }

    @Override
    public Page<Map<String, Object>> queryMyProc(String argUserId, Integer argCurrPage, Integer argPageSize) {
        Page<Map<String, Object>> page = extFlowableMapper.queryMyProc(new Page<Map>(argCurrPage, argPageSize), argUserId);
        return page;
    }

    @Override
    public Page<Map<String, Object>> queryMyDraft(String argUserId, Integer argCurrPage, Integer argPageSize) {
        Page<Map<String, Object>> page = extFlowableMapper.queryMyDraft(new Page<Map>(argCurrPage, argPageSize), argUserId);
        return page;
    }

    @Override
    public TaskDetail queryTaskDetail(String argMatterInstId, String argTaskId, Boolean argIsTaskDetailAttr, Boolean argIsTaskDetailBackHis) {
        MustParamValidation.mustValidation(argMatterInstId);
        // 查询事项实例
        TActMatterInstEntity tActMatterInstEntity = tActMatterInstMapper.selectById(argMatterInstId);
        if (AssertValid.isEmpty(tActMatterInstEntity))
            throw new ModuleFlowableException("事项实例ID不存在");

        TaskDetail convert = ObjectConvert.convert(tActMatterInstEntity, TaskDetail.class);
        convert.setIsFinish(false);
        convert.setTaskId(argTaskId);
        // 查询正文表单设计内容
        if (AssertValid.isNotEmpty(convert.getActFengFormId())) {
            String s = formService.queryFormDesigner(convert.getActFengFormId());
            convert.setFormDesigner(s);
        }
        // 查询正文表单数据
        LambdaQueryWrapper<TActMatterInstFormdataEntity> query = new LambdaQueryWrapper<>();
        query.eq(TActMatterInstFormdataEntity::getActMatterInstId, argMatterInstId);
        query.eq(TActMatterInstFormdataEntity::getDelFlag, 0);
        List<TActMatterInstFormdataEntity> tActMatterInstFormdataEntities = tActMatterInstFormdataMapper.selectList(query);
        Map<String, Object> collect = tActMatterInstFormdataEntities.stream().collect(Collectors.toMap(TActMatterInstFormdataEntity::getFormItem, v -> {
            String dataType = v.getDataType();
            Object o = ObjectUtil.parseObject(v.getFormValue(), dataType);
            return o;
        }));
        convert.setFormData(collect);

        // 查询任务概览
        List<TaskBrowse> objects = new ArrayList<>();
        List<ProcessInstance> list1 = runtimeService.createProcessInstanceQuery().processInstanceId(tActMatterInstEntity.getProcInstId()).list();
        List<HistoricProcessInstance> list2 = null;
        Boolean isHistory = false;
        // 如果流程定义结果为空，则去历史表中查询
        if (AssertValid.isEmpty(list1)) {
            list2 = historyService.createHistoricProcessInstanceQuery().processInstanceId(tActMatterInstEntity.getProcInstId()).list();
            isHistory = true;
        }

        List<TaskConfList> taskConfList = flowableService.getTaskConfList(isHistory ? list2.get(0).getProcessDefinitionId() : list1.get(0).getProcessDefinitionId());
        LambdaQueryWrapper<TActRuActinstEntity> query2 = new LambdaQueryWrapper<>();
        query2.eq(TActRuActinstEntity::getProcInstId, tActMatterInstEntity.getProcInstId());
        query2.eq(TActRuActinstEntity::getDelFlag, 0);
        query2.orderByAsc(TActRuActinstEntity::getCreateTime);
        List<TActRuActinstEntity> tActRuActinstEntities = tActRuActinstMapper.selectList(query2);

        for (TaskConfList confList : taskConfList) {
            TaskBrowse taskBrowse = new TaskBrowse().setTaskName(confList.getTaskName());
            taskBrowse.setTaskId(null); // 任务概览中没指定TASK_ID,原因是TaskConfList中的TASK_ID是任务定义ID，不是实例ID。如果需要这个值的话修改这块的代码
            for (TActRuActinstEntity tActRuActinstEntity : tActRuActinstEntities) {
                if (tActRuActinstEntity.getTaskDefKey().equals(confList.getTaskId())) {
                    taskBrowse.setProcTime(tActRuActinstEntity.getAcceptTime());
                    taskBrowse.setUserId(tActRuActinstEntity.getAcceptId());
                    taskBrowse.setUserName(tActRuActinstEntity.getAcceptName());
                    taskBrowse.setTaskId(tActRuActinstEntity.getTaskId());
                }
            }
            objects.add(taskBrowse);
        }
        convert.setTaskBrowseList(objects);
        // 查询流程节点耗时的数据
        List<HistoricTaskInstance> list3 = historyService.createHistoricTaskInstanceQuery().processInstanceId(tActMatterInstEntity.getProcInstId()).list();
        Map<String, String> costTimeMap = list3.stream().collect(Collectors.toMap(k -> {
            return k.getId();
        }, v -> {
            return (v == null || v.getDurationInMillis() == null) ? "0" : v.getDurationInMillis().toString();
        }));
        // 查询任务处理详情
        Map<String, String> collect2 = taskConfList.stream().collect(Collectors.toMap(TaskConfList::getTaskId, TaskConfList::getTaskName));
        List<TaskBrowseDetail> objects1 = new ArrayList<>();
        TaskBrowseDetail taskBrowseDetail = new TaskBrowseDetail();
        taskBrowseDetail.setRandomId(IdUtil.getStringId());
        taskBrowseDetail.setTaskName("提交");
        taskBrowseDetail.setProcTime(tActMatterInstEntity.getStartTime());
        taskBrowseDetail.setTaskId("-1");
        taskBrowseDetail.setUserId(tActMatterInstEntity.getStartUserId());
        taskBrowseDetail.setUserName(tActMatterInstEntity.getStartUserName());
        taskBrowseDetail.setIsAttr(false);
        objects1.add(taskBrowseDetail);

        for (TActRuActinstEntity tActRuActinstEntity : tActRuActinstEntities) {
            taskBrowseDetail = new TaskBrowseDetail();

            // ADD NEW
            taskBrowseDetail.setFormDesigner(this.formSupplement(tActRuActinstEntity.getTaskDefKey()));
            taskBrowseDetail.setFormContent(tActRuActinstEntity.getFormContent());

            taskBrowseDetail.setRandomId(IdUtil.getStringId());
            taskBrowseDetail.setFormInstId(tActRuActinstEntity.getFormInstId());
            taskBrowseDetail.setProcTime(tActRuActinstEntity.getAcceptTime());
            taskBrowseDetail.setUserId(tActRuActinstEntity.getAcceptId());
            taskBrowseDetail.setUserName(tActRuActinstEntity.getAcceptName());
            taskBrowseDetail.setTaskId(tActRuActinstEntity.getTaskId());
            taskBrowseDetail.setAttType(tActRuActinstEntity.getAttType());
            taskBrowseDetail.setAttDesc(tActRuActinstEntity.getAttDesc());
            taskBrowseDetail.setActRuActinstId(tActRuActinstEntity.getId());
            taskBrowseDetail.setTaskName(collect2.get(tActRuActinstEntity.getTaskDefKey()));
            taskBrowseDetail.setActionName(tActRuActinstEntity.getActionFunName());
            taskBrowseDetail.setActionCode(tActRuActinstEntity.getActionFunCode());
            // 拿到成本耗时
            String s = costTimeMap.get(tActRuActinstEntity.getTaskId());
            if (AssertValid.isEmpty(s))
                s = tActRuActinstEntity.getCostTime().toString();
            if (s != null && !s.trim().equals("") && !s.trim().equals("0")) {
                taskBrowseDetail.setCostMs(s);
                BigDecimal bigDecimal = new BigDecimal(s);

                // 豪秒转天
                BigDecimal bigDecimal1 = bigDecimal.divide(new BigDecimal("86400000"), 4, BigDecimal.ROUND_HALF_UP);
                taskBrowseDetail.setCostDays(bigDecimal1);

                // 豪秒转小时
                bigDecimal1 = bigDecimal.divide(new BigDecimal("3600000"), 2, BigDecimal.ROUND_HALF_UP);
                taskBrowseDetail.setCostHours(bigDecimal1);

                // 豪秒转分钟
                bigDecimal1 = bigDecimal.divide(new BigDecimal("60000"), 2, BigDecimal.ROUND_HALF_UP);
                taskBrowseDetail.setCostMins(bigDecimal1);

                // 豪秒转秒
                bigDecimal1 = bigDecimal.divide(new BigDecimal("1000"), 2, BigDecimal.ROUND_HALF_UP);
                taskBrowseDetail.setCostSecond(bigDecimal1);


            } else {
                taskBrowseDetail.setCostSecond(BigDecimal.ZERO);
                taskBrowseDetail.setCostMins(BigDecimal.ZERO);
                taskBrowseDetail.setCostMs("0");
                taskBrowseDetail.setCostHours(BigDecimal.ZERO);
            }

            if (AssertValid.isNotEmpty(tActRuActinstEntity.getIsAttr())) {
                taskBrowseDetail.setIsAttr(tActRuActinstEntity.getIsAttr().intValue() == 1 ? true : false);
            } else {
                taskBrowseDetail.setIsAttr(false);
            }
            if (AssertValid.isNotEmpty(tActRuActinstEntity.getIsForm())) {
                taskBrowseDetail.setIsForm(tActRuActinstEntity.getIsForm().intValue() == 1 ? true : false);
            } else {
                taskBrowseDetail.setIsForm(false);
            }
            // 得到任务节点名称
            for (TaskConfList confList : taskConfList) {
                if (confList.getTaskId().equals(tActRuActinstEntity.getTaskId())) {
                    taskBrowseDetail.setTaskName(confList.getTaskName());
                }
            }
            objects1.add(taskBrowseDetail);
        }
        convert.setTaskBrowseDetailList(new ArrayList<>());
        // 加载历史流程详情
        if (argIsTaskDetailBackHis) {
            convert.getTaskBrowseDetailList().addAll(queryFirstTaskBrowseDetail(costTimeMap, taskConfList, collect2, tActMatterInstEntity.getHisIds()));
        }
        // 加载当前流程详情
        convert.getTaskBrowseDetailList().addAll(objects1);
        // 加载后流程详情
        if (argIsTaskDetailBackHis) {
            String hisIds = tActMatterInstEntity.getHisIds();
            // 判断如果有原任务实例的情况下，拼接当前任务实例ID，这样才能查到后续的任务实例
            if (AssertValid.isNotEmpty(hisIds))
                convert.getTaskBrowseDetailList().addAll(queryLastTaskBrowseDetail(costTimeMap, taskConfList, collect2, hisIds + "," + argMatterInstId));
        }
        // 查询正文附件
        LambdaQueryWrapper<TActRuActinstAttrEntity> q = new LambdaQueryWrapper<>();
        q.eq(TActRuActinstAttrEntity::getProcInstId, tActMatterInstEntity.getProcInstId());
        q.eq(TActRuActinstAttrEntity::getDelFlag, 0);
        q.eq(TActRuActinstAttrEntity::getIsStart, 1);
        q.orderByAsc(TActRuActinstAttrEntity::getInx);
        List<TActRuActinstAttrEntity> tActRuActinstAttrEntities = tActRuActinstAttrMapper.selectList(q);
        convert.setAttrList(new ArrayList<>());
        tActRuActinstAttrEntities.forEach(s3 -> {
            WebFsDataResult webFsDataResult = new WebFsDataResult();
            String url = fsManagerInf.getUrl(s3.getSysFsId(), s3.getFsUri(), false);
            webFsDataResult.setUrl(url);
            webFsDataResult.setOriFileName(s3.getOriFileName());
            webFsDataResult.setSysFsId(s3.getSysFsId());
            webFsDataResult.setSysFlId(s3.getSysFlId());
            webFsDataResult.setUri(s3.getFsUri());
            convert.getAttrList().add(webFsDataResult);
        });
        // 判断是否有当前任务信息的查询需要
        if (AssertValid.isNotEmpty(argTaskId)) {
            List<Map<String, Object>> list = null;
            // 查询节点配置数据,包括任务节点配置，动作配置
            String sqlStr = "SELECT DISTINCT T.TASK_DEF_KEY_ FROM (\n" +
                    "select TASK_DEF_KEY_ from act_ru_task where id_= '" + argTaskId + "'\n" +
                    "UNION\n" +
                    "select TASK_DEF_KEY_ from act_hi_taskinst where id_='" + argTaskId + "'\n" +
                    ") T";
            list = jdbcTemplate.queryForList(sqlStr);
            TaskConfResult taskConfResult = flowableService.queryTaskConf(list.get(0).get("TASK_DEF_KEY_").toString());
            convert.setTaskConf(taskConfResult);
            convert.setActionList(taskConfResult.getActionEntity());

            // ADD B
            convert.setFormDesigner(this.formSupplement(taskConfResult.getTaskDefKey()));

            // 查询当前任务态度、节点态度说明
            LambdaQueryWrapper<TActRuActinstEntity> query3 = new LambdaQueryWrapper<>();
            query3.eq(TActRuActinstEntity::getTaskId, argTaskId);
            query3.eq(TActRuActinstEntity::getDelFlag, 0);
            List<TActRuActinstEntity> en = tActRuActinstMapper.selectList(query3);
            if (AssertValid.isNotEmpty(en)) {
                convert.setAttType(en.get(0).getAttType());
                convert.setAttDesc(en.get(0).getAttDesc());
            }
            // 查询当前任务附件
            q = new LambdaQueryWrapper<>();
            q.eq(TActRuActinstAttrEntity::getTaskId, argTaskId);
            q.eq(TActRuActinstAttrEntity::getDelFlag, 0);
            q.eq(TActRuActinstAttrEntity::getIsStart, 0);
            q.orderByAsc(TActRuActinstAttrEntity::getInx);
            tActRuActinstAttrEntities = tActRuActinstAttrMapper.selectList(q);
            convert.setTaskAttrList(new ArrayList<>());
            tActRuActinstAttrEntities.forEach(s4 -> {
                WebFsDataResult wr = new WebFsDataResult();
                String url = fsManagerInf.getUrl(s4.getSysFsId(), s4.getFsUri(), false);
                wr.setUrl(url);
                wr.setOriFileName(s4.getOriFileName());
                wr.setSysFsId(s4.getSysFsId());
                wr.setSysFlId(s4.getSysFlId());
                wr.setUri(s4.getFsUri());
                convert.getTaskAttrList().add(wr);
            });
            // 查询当前任务表单
            if (AssertValid.isNotEmpty(en) && en.get(0).getIsForm().intValue() == 1) {
                convert.setTaskFormDesigner(en.get(0).getActFengFormId());
                // 查询表单数据
                if (AssertValid.isNotEmpty(en.get(0).getFormInstId())) {
                    LambdaQueryWrapper<TActFengFormDataEntity> query4 = new LambdaQueryWrapper<>();
                    query4.eq(TActFengFormDataEntity::getFormInstId, en.get(0).getFormInstId());
                    query4.eq(TActFengFormDataEntity::getDelFlag, 0);
                    List<TActFengFormDataEntity> de = tActFengFormDataMapper.selectList(query4);
                    Map<String, String> collect1 = de.stream().collect(Collectors.toMap(TActFengFormDataEntity::getFormItem, TActFengFormDataEntity::getFormValue));
                    convert.setTaskFormData(collect1);
                }
            }
            // 当前任务的表单设计数据
            if (AssertValid.isNotEmpty(convert.getTaskFormData())) {
                // 如果表单有数据的情况下，从流程记录中的表单实例ID，找到当时的表单设计
                LambdaQueryWrapper<TActRuActinstEntity> rq = new LambdaQueryWrapper<TActRuActinstEntity>();
                rq.eq(TActRuActinstEntity::getTaskId, argTaskId);
                List<TActRuActinstEntity> enList = tActRuActinstMapper.selectList(rq);
                String actFengFormId = enList.get(0).getActFengFormId();
                if (AssertValid.isNotEmpty(actFengFormId)) {
                    FengForm fengForm = formService.queryFormListById(actFengFormId);
                    convert.setTaskFormDesigner(fengForm.getFormContent());
                }
            } else {
                // 如果没有数据的情况下查找任务配置过程中是否配置了表单KEY,跟据KEY查找最新的表单数据
                String formKey = taskConfResult.getFormKey();
                if (AssertValid.isNotEmpty(formKey)) {
                    FengForm fengForm = formService.queryFormByKey(formKey);
                    convert.setTaskFormDesigner(fengForm.getFormContent());
                }
            }
        }
        // 查询流程最终结果态度
        if (isHistory) {
            // 当isHistory为true时说明流程已经完成
            LambdaQueryWrapper<TActTheendEntity> qq = new LambdaQueryWrapper<>();
            qq.eq(TActTheendEntity::getProcInstId, tActMatterInstEntity.getProcInstId());
            qq.eq(TActTheendEntity::getDelFlag, 0);
            List<TActTheendEntity> tActTheendEntities = tActTheendMapper.selectList(qq);
            if (AssertValid.isNotEmpty(tActTheendEntities)) {
                TaskAtt convert1 = ObjectConvert.convert(tActTheendEntities.get(0), TaskAtt.class);
                convert.setFinishTime(convert1.getEndTime());
                convert.setLastAtt(convert1);
            }
        }
        if (AssertValid.isNotEmpty(convert.getLastAtt())) {
            convert.setIsFinish(true);
        }
        // 判断是否直接返回流程处理详情中的附件，如果需要返回的话在此处做下查询
        if (argIsTaskDetailAttr) {
            List<TaskBrowseDetail> taskBrowseDetailList = convert.getTaskBrowseDetailList();
            for (TaskBrowseDetail detail : taskBrowseDetailList) {
                if (detail.getIsAttr()) {
                    List<WebFsDataResult> webFsDataResults = queryTaskAttachmentList(detail.getActRuActinstId());
                    detail.setAttrList(webFsDataResults);
                }
            }
        }
        convert.setSystemCurrTime(new Date());
        // 取当前任务所处环节名称
        String sqlStr = "";
        sqlStr += " SELECT";
        sqlStr += "   a.ID,";
        sqlStr += "   b.ID_ AS taskId,";
        sqlStr += "   b.NAME_ AS taskName";
        sqlStr += " FROM";
        sqlStr += "   t_act_matter_inst a";
        sqlStr += "   LEFT JOIN act_ru_task b ON a.PROC_INST_ID_ = b.PROC_INST_ID_";
        sqlStr += " WHERE";
        sqlStr += "   a.id = '" + argMatterInstId + "'";
        List<Map<String, Object>> maps = jdbcTemplate.queryForList(sqlStr);
        if (AssertValid.isNotEmpty(maps)) {
            String taskNames = "";
            String taskIds = "";
            for (Map<String, Object> map : maps) {
                if (map.get("taskName") != null)
                    taskNames += "," + map.get("taskName").toString();
                else
                    taskNames += "," + "";

                if (map.get("taskId") != null)
                    taskIds += "," + map.get("taskId").toString();
                else
                    taskIds += "," + "";
            }
            if (!taskNames.equals(""))
                convert.setCurrTaskNames(taskNames.substring(1));
            else
                convert.setCurrTaskNames("");

            if (!taskIds.equals(""))
                convert.setCurrTaskIds(taskIds.substring(1));
            else
                convert.setCurrTaskIds("");
        }
        return convert;
    }

    /**
     * 查询任务详情
     *
     * @param costTimeMap
     * @param taskConfList
     * @param argTaskNameMapping
     * @param argMatterInstIds
     * @return
     */
    private List<TaskBrowseDetail> queryFirstTaskBrowseDetail(Map<String, String> costTimeMap, List<TaskConfList> taskConfList, Map<String, String> argTaskNameMapping, String argMatterInstIds) {

        List<TaskBrowseDetail> list = new ArrayList<TaskBrowseDetail>();
        if (AssertValid.isEmpty(argMatterInstIds))
            return list;
        String[] split = argMatterInstIds.split(",");
        // 查询历史的任务实例列表
        List<TActMatterInstEntity> miList = new ArrayList<>();
        for (int i = 0; i < split.length; i++) {
            TActMatterInstEntity tActMatterInstEntity = tActMatterInstMapper.selectById(split[i]);
            if (tActMatterInstEntity != null)
                miList.add(tActMatterInstEntity);
        }
        // 构建详情
        list = buildDetail(costTimeMap, taskConfList, argTaskNameMapping, miList);
        return list;
    }

    /**
     * 查询在此任务实例ID后的详情
     *
     * @param costTimeMap
     * @param taskConfList
     * @param argTaskNameMapping
     * @param argMatterInstIds
     * @return
     */
    private List<TaskBrowseDetail> queryLastTaskBrowseDetail(Map<String, String> costTimeMap, List<TaskConfList> taskConfList, Map<String, String> argTaskNameMapping, String argMatterInstIds) {
        List<TaskBrowseDetail> list = new ArrayList<TaskBrowseDetail>();
        if (AssertValid.isEmpty(argMatterInstIds))
            return list;
        LambdaQueryWrapper<TActMatterInstEntity> query = new LambdaQueryWrapper<TActMatterInstEntity>();
        query.likeRight(TActMatterInstEntity::getHisIds, argMatterInstIds);
        List<TActMatterInstEntity> miList = tActMatterInstMapper.selectList(query);
        list = buildDetail(costTimeMap, taskConfList, argTaskNameMapping, miList);
        return list;
    }

    private List<TaskBrowseDetail> buildDetail(Map<String, String> costTimeMap, List<TaskConfList> taskConfList, Map<String, String> argTaskNameMapping, List<TActMatterInstEntity> miList) {
        List<TaskBrowseDetail> list = new ArrayList<TaskBrowseDetail>();
        // 循环构建详情
        for (TActMatterInstEntity tActMatterInstEntity : miList) {

            TaskBrowseDetail taskBrowseDetail = new TaskBrowseDetail();
            taskBrowseDetail.setRandomId(IdUtil.getStringId());
            taskBrowseDetail.setTaskName("提交");
            taskBrowseDetail.setProcTime(tActMatterInstEntity.getStartTime());
            taskBrowseDetail.setTaskId("-1");
            taskBrowseDetail.setUserId(tActMatterInstEntity.getStartUserId());
            taskBrowseDetail.setUserName(tActMatterInstEntity.getStartUserName());
            taskBrowseDetail.setIsAttr(false);
            list.add(taskBrowseDetail);

            // 查询流程环节
            LambdaQueryWrapper<TActRuActinstEntity> query2 = new LambdaQueryWrapper<>();
            query2.eq(TActRuActinstEntity::getProcInstId, tActMatterInstEntity.getProcInstId());
            query2.eq(TActRuActinstEntity::getDelFlag, 0);
            query2.orderByAsc(TActRuActinstEntity::getCreateTime);
            List<TActRuActinstEntity> tActRuActinstEntities = tActRuActinstMapper.selectList(query2);

            for (TActRuActinstEntity tActRuActinstEntity : tActRuActinstEntities) {
                taskBrowseDetail = new TaskBrowseDetail();

                // ADD C
                taskBrowseDetail.setFormContent(tActRuActinstEntity.getFormContent());

                taskBrowseDetail.setRandomId(IdUtil.getStringId());
                taskBrowseDetail.setFormInstId(tActRuActinstEntity.getFormInstId());
                taskBrowseDetail.setProcTime(tActRuActinstEntity.getAcceptTime());
                taskBrowseDetail.setUserId(tActRuActinstEntity.getAcceptId());
                taskBrowseDetail.setUserName(tActRuActinstEntity.getAcceptName());
                taskBrowseDetail.setTaskId(tActRuActinstEntity.getTaskId());
                taskBrowseDetail.setAttType(tActRuActinstEntity.getAttType());
                taskBrowseDetail.setAttDesc(tActRuActinstEntity.getAttDesc());
                taskBrowseDetail.setActRuActinstId(tActRuActinstEntity.getId());
                taskBrowseDetail.setTaskName(argTaskNameMapping.get(tActRuActinstEntity.getTaskDefKey()));
                taskBrowseDetail.setActionName(tActRuActinstEntity.getActionFunName());
                taskBrowseDetail.setActionCode(tActRuActinstEntity.getActionFunCode());
                // 拿到成本耗时
                String s = costTimeMap.get(tActRuActinstEntity.getTaskId());
                if (AssertValid.isEmpty(s))
                    s = tActRuActinstEntity.getCostTime().toString();
                if (s != null && !s.trim().equals("") && !s.trim().equals("0")) {
                    taskBrowseDetail.setCostMs(s);
                    BigDecimal bigDecimal = new BigDecimal(s);

                    // 豪秒转天
                    BigDecimal bigDecimal1 = bigDecimal.divide(new BigDecimal("86400000"), 4, BigDecimal.ROUND_HALF_UP);
                    taskBrowseDetail.setCostDays(bigDecimal1);

                    // 豪秒转小时
                    bigDecimal1 = bigDecimal.divide(new BigDecimal("3600000"), 2, BigDecimal.ROUND_HALF_UP);
                    taskBrowseDetail.setCostHours(bigDecimal1);

                    // 豪秒转分钟
                    bigDecimal1 = bigDecimal.divide(new BigDecimal("60000"), 2, BigDecimal.ROUND_HALF_UP);
                    taskBrowseDetail.setCostMins(bigDecimal1);

                    // 豪秒转秒
                    bigDecimal1 = bigDecimal.divide(new BigDecimal("1000"), 2, BigDecimal.ROUND_HALF_UP);
                    taskBrowseDetail.setCostSecond(bigDecimal1);
                } else {
                    taskBrowseDetail.setCostSecond(BigDecimal.ZERO);
                    taskBrowseDetail.setCostMins(BigDecimal.ZERO);
                    taskBrowseDetail.setCostMs("0");
                    taskBrowseDetail.setCostHours(BigDecimal.ZERO);
                }


                if (AssertValid.isNotEmpty(tActRuActinstEntity.getIsAttr())) {
                    taskBrowseDetail.setIsAttr(tActRuActinstEntity.getIsAttr().intValue() == 1 ? true : false);
                } else {
                    taskBrowseDetail.setIsAttr(false);
                }
                if (AssertValid.isNotEmpty(tActRuActinstEntity.getIsForm())) {
                    taskBrowseDetail.setIsForm(tActRuActinstEntity.getIsForm().intValue() == 1 ? true : false);
                } else {
                    taskBrowseDetail.setIsForm(false);
                }
                // 得到任务节点名称
                for (TaskConfList confList : taskConfList) {
                    if (confList.getTaskId().equals(tActRuActinstEntity.getTaskId())) {
                        taskBrowseDetail.setTaskName(confList.getTaskName());
                    }
                }
                list.add(taskBrowseDetail);
            }
        }
        return list;
    }

    @Override
    public TaskBrowseDetailFormData queryTaskFormData(String argActRuActinstId) {

        LambdaQueryWrapper<TActRuActinstEntity> query2 = new LambdaQueryWrapper<>();
        query2.eq(TActRuActinstEntity::getId, argActRuActinstId);
        query2.eq(TActRuActinstEntity::getDelFlag, 0);
        List<TActRuActinstEntity> tActRuActinstEntities = tActRuActinstMapper.selectList(query2);
        if (AssertValid.isEmpty(tActRuActinstEntities))
            throw new ModuleFlowableException("工作流过程信息记录ID不存在");

        // 查表单设计数据
        TActRuActinstEntity tActRuActinstEntity = tActRuActinstEntities.get(0);
        TaskBrowseDetailFormData taskBrowseDetailFormData = new TaskBrowseDetailFormData();
        String s = formService.queryFormDesigner(tActRuActinstEntity.getActFengFormId());
        taskBrowseDetailFormData.setFormDesigner(s);
        // 查表单数据
        LambdaQueryWrapper<TActFengFormDataEntity> query = new LambdaQueryWrapper<>();
        query.eq(TActFengFormDataEntity::getFormInstId, tActRuActinstEntity.getFormInstId());
        query.eq(TActFengFormDataEntity::getDelFlag, 0);
        List<TActFengFormDataEntity> tActFengFormDataEntities = tActFengFormDataMapper.selectList(query);
        Map<String, Object> collect = tActFengFormDataEntities.stream().collect(Collectors.toMap(TActFengFormDataEntity::getFormItem, v -> {
            String dataType = v.getDataType();
            Object o = ObjectUtil.parseObject(v.getFormValue(), dataType);
            return o;
        }));
        taskBrowseDetailFormData.setFormData(collect);

        // 查附件
        LambdaQueryWrapper<TActRuActinstAttrEntity> query3 = new LambdaQueryWrapper<>();
        query3.eq(TActRuActinstAttrEntity::getTaskId, tActRuActinstEntity.getTaskId());
        query3.eq(TActRuActinstAttrEntity::getIsStart, 0);
        query3.orderByAsc(TActRuActinstAttrEntity::getInx);

        List<TActRuActinstAttrEntity> tActRuActinstAttrEntities = tActRuActinstAttrMapper.selectList(query3);
        List<WebFsDataResult> collect1 = tActRuActinstAttrEntities.stream().map(ss -> {
            WebFsDataResult webFsDataResult = new WebFsDataResult();
            webFsDataResult.setSysFlId(ss.getSysFlId());
            webFsDataResult.setSysFsId(ss.getSysFsId());
            String url = fsManagerInf.getUrl(ss.getSysFsId(), ss.getFsUri(), false);
            webFsDataResult.setUrl(url);
            webFsDataResult.setUri(ss.getFsUri());
            webFsDataResult.setOriFileName(ss.getOriFileName());
            return webFsDataResult;
        }).collect(Collectors.toList());
        taskBrowseDetailFormData.setAttachmentList(collect1);

        return taskBrowseDetailFormData;
    }

    @Override
    public List<WebFsDataResult> queryTaskAttachmentList(String argActRuActinstId) {
        LambdaQueryWrapper<TActRuActinstEntity> query2 = new LambdaQueryWrapper<>();
        query2.eq(TActRuActinstEntity::getId, argActRuActinstId);
        query2.eq(TActRuActinstEntity::getDelFlag, 0);
        List<TActRuActinstEntity> tActRuActinstEntities = tActRuActinstMapper.selectList(query2);
        if (AssertValid.isEmpty(tActRuActinstEntities))
            throw new ModuleFlowableException("工作流过程信息记录ID不存在");
        TActRuActinstEntity tActRuActinstEntity = tActRuActinstEntities.get(0);
        // 查附件
        LambdaQueryWrapper<TActRuActinstAttrEntity> query3 = new LambdaQueryWrapper<>();
        query3.eq(TActRuActinstAttrEntity::getTaskId, tActRuActinstEntity.getTaskId());
        query3.eq(TActRuActinstAttrEntity::getIsStart, 0);
        query3.orderByAsc(TActRuActinstAttrEntity::getInx);

        List<TActRuActinstAttrEntity> tActRuActinstAttrEntities = tActRuActinstAttrMapper.selectList(query3);
        List<WebFsDataResult> collect1 = tActRuActinstAttrEntities.stream().map(ss -> {
            WebFsDataResult webFsDataResult = new WebFsDataResult();
            webFsDataResult.setSysFlId(ss.getSysFlId());
            webFsDataResult.setSysFsId(ss.getSysFsId());
            String url = fsManagerInf.getUrl(ss.getSysFsId(), ss.getFsUri(), false);
            webFsDataResult.setUrl(url);
            webFsDataResult.setUri(ss.getFsUri());
            webFsDataResult.setOriFileName(ss.getOriFileName());
            return webFsDataResult;
        }).collect(Collectors.toList());
        return collect1;
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public void save(String argMatterInstId, String argTaskId, Integer argAttType, String argAttDesc, Map<String, Object> argFormData, List<Attr> argAttrList, String argActionFunname, String argActionFuncode,String formContent) {
        MustParamValidation.mustValidation(argMatterInstId, argTaskId, argAttType);
        SystemUser loginUser = SystemUserUtil.getSystemUser();
        DateTime now = DateTime.now();
        // 查询任务实例过程信息记录中的最后动作时间
        List<Map<String, Object>> maps = jdbcTemplate.queryForList("select MAX(CREATE_TIME) as maxTime from T_ACT_RU_ACTINST where ACT_MATTER_INST_ID='" + argMatterInstId + "'");
        Date lastProcTime = now.toDate();
        Long costTime = 0l;
        if (AssertValid.isNotEmpty(maps)) {
            if (AssertValid.isNotEmpty(maps.get(0).get("maxTime"))) {
                lastProcTime = Date.from(((LocalDateTime) maps.get(0).get("maxTime")).atZone(ZoneId.systemDefault()).toInstant());
                costTime = now.toDate().getTime() - lastProcTime.getTime();
            } else {
                // 如果没查到最后一次的处理记录，则查询事项的提交时间
                maps = jdbcTemplate.queryForList("select CREATE_TIME as maxTime from t_act_matter_inst WHERE ID ='" + argMatterInstId + "'");
                lastProcTime = Date.from(((LocalDateTime) maps.get(0).get("maxTime")).atZone(ZoneId.systemDefault()).toInstant());
                costTime = now.toDate().getTime() - lastProcTime.getTime();
            }
        }

        // 查询事项实例信息，找到表单
        TActMatterInstEntity matterinstEn = tActMatterInstMapper.selectById(argMatterInstId);
        if (AssertValid.isEmpty(matterinstEn))
            throw new ModuleFlowableException("事项实例ID不存在");
        // 查询正文表单设计内容
        String s = formService.queryFormDesigner(matterinstEn.getActFengFormId());
        // 保存任务节点态度信息
        TActRuActinstEntity actinstsEn = new TActRuActinstEntity().setId(IdUtil.getStringId()).setCreateBy(loginUser.getRealname()).setCreateTime(now.toDate()).setUpdateBy(loginUser.getRealname()).setUpdateTime(now.toDate()).setDelFlag(0);
        actinstsEn.setFormContent(formContent);
        actinstsEn.setAcceptId(loginUser.getId());
        actinstsEn.setAcceptName(loginUser.getRealname());
        actinstsEn.setAcceptTime(now.toDate());
        actinstsEn.setAttType(argAttType);
        actinstsEn.setAttDesc(argAttDesc);
        actinstsEn.setActMatterInstId(argMatterInstId);
        actinstsEn.setActionFunName(argActionFunname);
        actinstsEn.setActionFunCode(argActionFuncode);
        // 保存成本耗时
        actinstsEn.setCostTime(costTime);
        // 保存流程相关ID数据
        List<ProcessInstance> list = runtimeService.createProcessInstanceQuery().processInstanceId(matterinstEn.getProcInstId()).list();
        actinstsEn.setProcDefId(list.get(0).getProcessDefinitionId());
        actinstsEn.setProcInstId(matterinstEn.getProcInstId());
        actinstsEn.setTaskId(argTaskId);
        // 保存任务节点表单信息
        actinstsEn.setIsForm(0);
        // 查询任务定义KEY
        List<Task> list1 = taskService.createTaskQuery().taskId(argTaskId).list();
        if (AssertValid.isEmpty(list1))
            throw new ModuleFlowableException("任务ID不存在");
        actinstsEn.setTaskDefKey(list1.get(0).getTaskDefinitionKey());
        List<TActFengFormDataEntity> dataEn = new ArrayList<>();
        TaskConfResult taskConfResult = flowableService.queryTaskConf(list1.get(0).getTaskDefinitionKey());
        if (AssertValid.isNotEmpty(taskConfResult.getFormKey())) {
            // 生成表单实例ID
            String formInstId = IdUtil.getStringId();
            actinstsEn.setFormInstId(formInstId);
            FengForm fengForm1 = null;
            if (AssertValid.isNotEmpty(taskConfResult.getFormKey())) {
                fengForm1 = formService.queryFormByKey(taskConfResult.getFormKey());
                actinstsEn.setActFengFormId(fengForm1.getId());
                actinstsEn.setIsForm(1);
            } else {
                actinstsEn.setIsForm(0);
            }
            if (AssertValid.isNotEmpty(argFormData)) {
                Iterator<String> iterator = argFormData.keySet().iterator();
                // 查询表单信息

                while (iterator.hasNext()) {
                    String next = iterator.next();
                    TActFengFormDataEntity en = new TActFengFormDataEntity().setId(IdUtil.getStringId()).setCreateBy(loginUser.getRealname()).setCreateTime(now.toDate()).setUpdateBy(loginUser.getRealname()).setUpdateTime(now.toDate()).setDelFlag(0);
                    en.setFormInstId(formInstId);
                    en.setActFengFormId(fengForm1.getId());
                    en.setProcInstId(matterinstEn.getProcInstId());
                    en.setFormKey(fengForm1.getFormKey());
                    en.setTaskDefKey(list1.get(0).getTaskDefinitionKey());
                    en.setTaskId(argTaskId);
                    en.setFormItem(next);

                    String formDataType = ObjectUtil.getFormDataType(argFormData.get(next));
                    en.setDataType(formDataType);

                    if (argFormData.get(next) != null) {

                        if (formDataType.equals("list") || formDataType.equals("object")) {
                            Object o1 = argFormData.get(next);
                            String s1 = JSONObject.toJSONString(o1);
                            en.setFormValue(s1);
                        } else {
                            en.setFormValue(argFormData.get(next).toString().trim());
                        }
                    } else
                        en.setFormValue("");
                    dataEn.add(en);
                }
                if (dataEn.size() > 1)
                    actinstsEn.setIsForm(1);
            }
        }
        // 保存任务节点附件信息
        actinstsEn.setIsAttr(0);
        ArrayList<TActRuActinstAttrEntity> attrEn = new ArrayList<>();
        int i = 0;
        if (AssertValid.isNotEmpty(argAttrList)) {
            for (Attr attr : argAttrList) {
                TActRuActinstAttrEntity en = new TActRuActinstAttrEntity().setId(IdUtil.getStringId()).setCreateBy(loginUser.getRealname()).setCreateTime(now.toDate()).setUpdateBy(loginUser.getRealname()).setUpdateTime(now.toDate()).setDelFlag(0);
                en.setSysFsId(attr.getSysFsId());
                en.setSysFlId(attr.getSysFlId());
                en.setProcInstId(matterinstEn.getProcInstId());
                en.setOriFileName(attr.getOriFileName());
                en.setTaskId(argTaskId);
                en.setIsStart(0);
                en.setInx(++i);
                en.setFsUri(attr.getUri());
                // 处理扩展名
                String extName = "";
                if (attr.getOriFileName() != null) {
                    String[] split = attr.getOriFileName().split("\\.");
                    if (split.length > 1)
                        extName = attr.getOriFileName().split("\\.")[1];
                }
                en.setFileExtension(extName.toLowerCase());
                en.setActRuActinstId(actinstsEn.getId());
                attrEn.add(en);
            }
            if (attrEn.size() > 0)
                actinstsEn.setIsAttr(1);
        }

        // 数据库操作
        tActRuActinstMapper.insert(actinstsEn);
        if (AssertValid.isNotEmpty(dataEn)) {
            iTActFengFormDataService.saveBatch(dataEn);
        }
        if (AssertValid.isNotEmpty(attrEn)) {
            iTActRuActinstAttrService.saveBatch(attrEn);
        }
    }

    /**
     * 表单补充信息（formDesigner）
     *
     * @param taskDefKey 任务定义Key
     * @return formDesigner
     */
    private String formSupplement(String taskDefKey) {
        LambdaQueryWrapper<TActTaskConfEntity> queryWrapper2 = new LambdaQueryWrapper<TActTaskConfEntity>();
        queryWrapper2.eq(TActTaskConfEntity::getTaskDefKey, taskDefKey);
        List<TActTaskConfEntity> tActTaskConfEntities = tActTaskConfMapper.selectList(queryWrapper2);
        if (CollectionUtils.isNotEmpty(tActTaskConfEntities)) {
            return tActTaskConfEntities.get(0).getFormDesigner();
        }
        return null;
    }
}